package com.yyy.spring6.bean;

import com.yyy.spring6.anno.Bean;
import com.yyy.spring6.anno.Di;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @Project ：learn_spring
 * @File ：AnnotationApplicationContext.java
 * @IDE ：IntelliJ IDEA
 * @Author ：自由如风间
 * @Date ：2025/3/31 17:10
 * @Description ：For study.
 */

public class AnnotationApplicationContext implements ApplicationContext {

    // 创建一个Map集合，用于放bean集合
    private static Map<Class, Object> beanFactory = new HashMap<>();
    private static String rootPath;

    // 返回对象
    @Override
    public Object getBean(Class clazz) {
        return beanFactory.get(clazz);
    }

    // 设置包扫描规则
    // 当前包及其子包，哪个类有@Bean注解，把这个类通过反射实例化

    public AnnotationApplicationContext(String basePackage) {
        try {
            // 把.替换成\
            String packagePath = basePackage.replaceAll("\\.", "\\\\");
            // 获取包的绝对路径
            Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packagePath);
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
                // 获取包前面的路径
                rootPath = filePath.substring(0, filePath.length() - packagePath.length());
                // 包扫描
                loadBean(new File(filePath));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void loadBean(File file) {
        // 判断当前是否是文件夹
        if (file.isDirectory()) {
            // 获取文件夹里所有内容
            File[] childrenFiles = file.listFiles();

            // 判断文件夹里面是否为空，为空直接返回
            if (childrenFiles == null || childrenFiles.length == 0) {
                return;
            }

            for (File child : childrenFiles) {
                if (child.isDirectory()) {
                    loadBean(child);
                } else {
                    String pathWithClass = child.getAbsolutePath().substring(rootPath.length() - 1);
                    if (pathWithClass.endsWith(".class")) {
                        String fullName = pathWithClass.replaceAll("\\\\", ".")
                                .replaceAll(".class", "");
                        try {
                            Class<?> clazz = Class.forName(fullName);
                            // 如果不是接口
                            if (!clazz.isInterface()) {
                                // 判断类上面是否有注解@Bean
                                Bean annotation = clazz.getAnnotation(Bean.class);
                                if (annotation != null) {
                                    try {
                                        // 实例化
                                        Object instance = clazz.getConstructor().newInstance();
                                        // 对象实例化过后，放到map集合的beanFactory里
                                        // 如果当前类有接口，让接口class作为map的键
                                        if (clazz.getInterfaces().length > 0) {
                                            beanFactory.put(clazz.getInterfaces()[0], instance);
                                        } else {
                                            beanFactory.put(clazz, instance);
                                        }
                                    } catch (InstantiationException | IllegalAccessException |
                                             InvocationTargetException | NoSuchMethodException e) {
                                        throw new RuntimeException(e);
                                    }
                                }
                            }
                        } catch (ClassNotFoundException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        }
    }

    // 属性注入
    private void loadDi() {
        Set<Map.Entry<Class, Object>> entries = beanFactory.entrySet();
        for (Map.Entry<Class, Object> entry : entries) {
            Object obj = entry.getValue();
            Class<?> clazz = obj.getClass();
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field field : declaredFields) {
                Di annotation = field.getAnnotation(Di.class);
                if (annotation != null) {
                    field.setAccessible(true);
                    // 如果有@Di注解，把对象进行设置（注入）
                    try {
                        // 根据类型进行注入
                        field.set(obj, beanFactory.get(field.getType()));
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
    }
}
